/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.chl.angholt.bookproject.db;

import edu.chl.angholt.bookproject.db.entity.Book;
import edu.chl.angholt.bookproject.db.entity.Book_;
import edu.chl.angholt.bookproject.db.exception.NonexistentEntityException;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

/**
 *
 * @author Jonas
 * Controller class for the book entity
 */
public class BookJpaCtrl extends EntityJpaCtrl<Book> {

    public BookJpaCtrl(EntityManagerFactory emf) {
        super(emf);
    }

    /**
     * Remove a book from the database
     * @param id The Id of the book to remove
     * @throws NonexistentEntityException If no book with that Id can be found
     */
    @Override
    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();


        tx.begin();
        Book b = em.find(Book.class, id);

        if (b == null) {
            throw new NonexistentEntityException("Can not remove entity because it does not exist");
        }


        em.remove(b);
        tx.commit();

        em.close();
    }

    /**
     * Find the specified book
     * @param id The id of the book to find
     * @return The found book
     */
    @Override
    public Book findEntity(Long id) {
        EntityManager em = emf.createEntityManager();
        return em.find(Book.class, id);
    }

    /**
     * Finds all books in the database
     * @return A list of all books in the database
     */
    @Override
    public List<Book> findEntities() {
        EntityManager em = emf.createEntityManager();
        CriteriaBuilder builder = em.getCriteriaBuilder();

        CriteriaQuery<Book> query = builder.createQuery(Book.class);
        Root<Book> b = query.from(Book.class);

        query.select(b);

        TypedQuery<Book> tq = em.createQuery(query);
        List<Book> books = tq.getResultList();
        em.close();
        return books;
    }

    /**
     * Finds a subset of books from the database.
     * @param maxResults The maximum number of books to find
     * @param firstResult The position of the first book to find
     * @return A list of the found books
     */
    @Override
    public List<Book> findEntities(int maxResults, int firstResult) {
        EntityManager em = emf.createEntityManager();
        CriteriaBuilder builder = em.getCriteriaBuilder();

        CriteriaQuery<Book> query = builder.createQuery(Book.class);
        Root<Book> b = query.from(Book.class);

        query.select(b);

        TypedQuery<Book> tq = em.createQuery(query);
        tq.setFirstResult(firstResult);
        tq.setMaxResults(maxResults);
        List<Book> books = tq.getResultList();
        em.close();
        return books;
    }

    /**
     * 
     * @return The number of books in the database
     */
    @Override
    public int getEntityCount() {
        return findEntities().size();
    }

    /**
     * Find the specified book and returns it
     * @param title The title of the book to find
     * @return The found book or null if no book with that title could be found
     */
    public Book findBook(String title) {
        EntityManager em = emf.createEntityManager();

        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Book> query = builder.createQuery(Book.class);
        Root<Book> b = query.from(Book.class);

        query.select(b).where(builder.equal(b.get(Book_.title), title));
        TypedQuery tq = em.createQuery(query);

        Book book;
        try {
            book = (Book) tq.getSingleResult();
        } catch (NoResultException e) {
            book = null;
        }
        em.close();
        return book;
    }

    /**
     * Find the books that contains pattern and returns them
     * @param title The title of the book to find
     * @return The found book or null if no book with that title could be found
     */
    public List<Book> findBookLike(String patern) {
        EntityManager em = emf.createEntityManager();
        patern = "%" + patern + "%";
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Book> query = builder.createQuery(Book.class);
        Root<Book> b = query.from(Book.class);

        query.select(b).where(builder.like(b.get(Book_.title), patern));
        TypedQuery<Book> tq = em.createQuery(query);

        List<Book> books = tq.getResultList();

        em.close();
        return books;
    }

    public void updateBook(Book book)throws NonexistentEntityException {
        EntityManager em = emf.createEntityManager();
  
        try {
            em.getTransaction().begin();

            Book b = findEntity(book.getBookId());
            b.setTitle(book.getTitle());
            b.setAuthor(book.getAuthor());
            b.setSynopsis(book.getSynopsis());
            b.setOriginalLanguage(book.getOriginalLanguage());
            b.setFirstRelease(book.getFirstRelease());
            b.setPublisher(book.getPublisher());
            //update
            em.merge(b);
            em.getTransaction().commit();
            
        } catch (Exception e) {
            System.out.println(e.getMessage());
             throw new NonexistentEntityException("Can not update entity");
        } finally {
            em.close();
        }
    }
}
